package com.asa.control_theory;

import java.util.ArrayList;
import java.util.List;

import com.asa.HanShu;
import com.asa.hutils.MathHUtils;
import com.asa.hutils.Ni;

public class A  {

	/**
	 * 矩阵指数函数的算法
	 * @param A	状态方程
	 * @param t	输入
	 * @param n	迭代次数，越多，越准，但越越好性能
	 * @return
	 */
	public static double[][] eAt(double[][] A,double t,int n) {//如果这个运算次数比较多，最好是把每次的参数记录下来，这样比较节约计算

		double[][] I = MathHUtils.getI(A.length);
		double[][] asa = I;
		double[][] suanzi = I;//我主营到A的n次方，每次都会项上进行叠加，这里记录上一次的，那么这次就只用进行一次乘以A的操作了
		double suanzijiecheng = 1;
		double suanziT = 1;

		for (int j = 1; j <= n; j++) {
			
			
			suanzi = MathHUtils.chenfa(suanzi, A);
			suanzijiecheng = suanzijiecheng*j;
			suanziT = suanziT * t;
			
			
			double[][] chenfa = MathHUtils.chenfa(suanzi, suanziT/suanzijiecheng);
			
			asa = MathHUtils.jiafa(asa, chenfa);

		}
		
		return asa;
		
//		double result =Ni.hangleishivalue(asa);
//		
//		
//		return result;
		
		
	}
	

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 特征值，直接调用高等代数的代码
	 * @return
	 */
	public static double[] tezhengzhi(double[][] a) {
		
		
		double[] r = MathHUtils.juzhengtezhengzhi(a);
		return r;
		
	}
	
	
	/**
	 * 特征向量
	 * @param a
	 * @return
	 */
	public static double[][] tezhengxiangliang(double[][] a) {
		
		double[][] juzhengtezhengxiangliang = null;
		try {
			juzhengtezhengxiangliang = MathHUtils.juzhengtezhengxiangliang(a);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return juzhengtezhengxiangliang;
		
	}
	
	
	
	
	/**
	 * 根据特征值来获取微分方程中的一个通解的集合
	 * 
	 * X* = AX
	 * X = PY		这儿的P是特征向量组成的矩阵，补充：有P(-1)AP得出来的是特征值的对角矩阵
	 * AX = APY
	 * 
	 * 由于X* = AX
	 * PY* = APY
	 * 
	 * P(-1)PY* = P(-1)APY
	 * Y* = 特征值对角矩阵*Y
	 * 
	 * 这里求出来的就是Y对应到t的解
	 * yi = Ci*Math.exp(特征值*t)
	 * 
	 * 
	 * 画出来看效果的话，现在还只支持2维的（2020-07-08）
	 */
	public static HanShu[] tongjieYiBytezhengzhi(final double[] tezhengzhi) {
		
		HanShu[] hanshuArr = new HanShu[tezhengzhi.length];
		
		for (int i = 0; i < tezhengzhi.length; i++) {
			final int asa = i;
			hanshuArr[asa] = new HanShu() {
				
				@Override
				public double hanshu(double t, double x) {
					// TODO Auto-generated method stub
					return 0;
				}
				
				@Override
				public double hanshu(double x) {
					// TODO Auto-generated method stub
					
					return Math.exp(tezhengzhi[asa]*x);
				}
			};	
		}
		return hanshuArr;
		
	}
	
	/**
	 * 得出X的解的线性组合的基础元素的 原理是
	 * X = PY	各个元的意思看tongjieYiBytezhengzhi方法的注释
	 * 得出
	 * xi = p[i][0]C1*Math.exp(特征值1*t) + p[i][1]C2**Math.exp(特征值2*t)... 这种形式的解
	 * 
	 * 这里不会把Ci放入，另起一个函数来存储最终函数簇的集合
	 * 
	 * @param tezhengzhi
	 * @param n
	 * @return
	 */
	public static List<List<HanShu>> tongjieXiByYi(final HanShu[] yi,double[][] p) {
		
		p = MathHUtils.zhuanzhi(p);
		List<List<HanShu>> result = new ArrayList<List<HanShu>>();
		
		
		for (int i = 0; i < p.length; i++) {
			
				final double[] ds = p[i];
				List<HanShu> xi = new ArrayList<HanShu>();

				System.out.println("dsdsdsdsdsdsdsdsdsdsds  "+ds.length);
				for (int k = 0; k < ds.length; k++) {
					final int kk = k;
					xi.add(new HanShu() {
						
						@Override
						public double hanshu(double t, double x) {
							// TODO Auto-generated method stub
							return 0;
						}
						
						@Override
						public double hanshu(double x) {
							// TODO Auto-generated method stub
							return yi[kk].hanshu(x)*ds[kk];
						}
					});
					
					
				}	
				result.add(xi);

			
			
		}
		
		
		return result;
	}

	/**
	 * 根据Ci来得取函数解的一个特解
	 * 
	 * @param xi
	 * @param ci
	 * @return
	 */
	public static List<HanShu> tongjieXiByXiCi(List<List<HanShu>> xi,final double[] ci) {
		
		List<HanShu> result = new ArrayList<HanShu>();
		
		
		for (int i = 0; i < xi.size(); i++) {
			final List<HanShu> xii = xi.get(i);
//			System.out.println(xii.size()+"     xii.size()   ");
			
			result.add(new HanShu() {
				
				@Override
				public double hanshu(double t, double x) {
					// TODO Auto-generated method stub
					return 0;
				}
				
				@Override
				public double hanshu(double x) {
					// TODO Auto-generated method stub
					double y = 0;
					for (int j = 0; j < xii.size(); j++) {
//						System.out.println("为什么 j会角标逸出呢"+ci.length + "   "+ j);

						y += xii.get(j).hanshu(x)
								*ci[j];
					}
					
					
					return y;
				}
			});
			
		}
		
		return result;
	}

	/**
	 * 为了生成簇，就是很多条线，来画图，这个方法就是做这个的，其内部主要是生成不同的Ci
	 * 这个就是为了我方便的
	 * @param xi
	 * @param n
	 * @return
	 */
	public static List<List<HanShu>> tongjieXiCiList(List<List<HanShu>> xi,int n){
		
		List<Double> cis = new ArrayList<Double>();
		cis.add(0.0);
		int size = xi.size();
		System.out.println("sizesizesizesizesizesize"+size);
		
		for (int i = 1; i < n; i++) {
			cis.add(i+0.0);
			cis.add(-1*(i+0.0));
		}
		
		List<List<Double>> zuhe = zuhe(cis, size);
		System.out.println("zuhedaxiao cis.size()"+cis.size());
		System.out.println("zuhedaxiao size"+size);
		System.out.println("zuhe的大小"+zuhe.size());
		for (int i = 0; i < zuhe.size(); i++) {
			for (int j = 0; j < zuhe.get(i).size(); j++) {
				System.out.print(zuhe.get(i).get(j) +"      " );
			}
			System.out.println();
		}
		
		
		
		
		List<List<HanShu>> result = new ArrayList<List<HanShu>>();
		
		for (int i = 0; i < zuhe.size(); i++) {
			final List<Double> C = zuhe.get(i);
			List<HanShu> resultitem = new ArrayList<HanShu>();
			double[] ci = new double[C.size()];
			for (int j = 0; j < C.size(); j++) {
				ci[j] = C.get(j);
			}
//			System.out.println(ci.length+"  ci.length    ");
			
			
			resultitem = tongjieXiByXiCi(xi, ci);
			result.add(resultitem);
			
//			for (int j = 0; j < xi.size(); j++) {
//				final List<HanShu> list = xi.get(j);
				
				
				
				
				
//				resultitem.add(new HanShu() {
//					
//					@Override
//					public double hanshu(double t, double x) {
//						// TODO Auto-generated method stub
//						return 0;
//					}
//					
//					@Override
//					public double hanshu(double x) {
//						// TODO Auto-generated method stub
//						double resulthanshu = 0;
//						for (int k = 0; k < list.size(); k++) {
//							resulthanshu += C.get(k) + list.get(k).hanshu(x);
//						}
//						
//						
//						return resulthanshu;
//					}
//				});
//				result.add(resultitem);	
//			}
			
		}
		
		return result;
	}
	
	
	
	/**
	 * 
	 * @param cis	
	 * @param size	大小
	 * @return
	 */
	public static List<List<Double>> zuhe(List<Double> cis,int size) {	
		
		List<Integer> alltimes = new ArrayList<Integer>();//用这个东西来记录index
		for (int i = 0; i < size; i++) {
			alltimes.add(0);
		}
		
		
		
		List<List<Double>> result = new ArrayList<List<Double>>();
		System.out.println("开始循环了，开始循环了，开始循环了，开始循环了，开始循环了，开始循环了");
		int index= 0;
		
		while(true) {
//			System.out.println(index++);
			
			List<Double> one = new ArrayList<Double>();
			for (int i = 0; i < alltimes.size(); i++) {
				one.add(cis.get(alltimes.get(i)));
//				System.out.print(alltimes[i]+"   ");
			}
//			System.out.println();
			
//			System.out.println("--------------------------");
			result.add(one);
			//对于进制的计算
			Integer dagqianzhi = alltimes.get(0)+1;
			asa(cis.size(), alltimes, 0, dagqianzhi);
			if (alltimes.get(0)<0) {
				System.out.println(alltimes.get(0)+"break"+size);
				break;
			}
			
				
			

		}
		
		return result;
	}
	
	
	
	/**
	 * 
	 * 如果结果超出了当前位数所能表达的，将吧所有位置上的数设置为-1
	 * @param jingzhi	需要计算的进制 -1
	 * @param jisuan	当前数的list 没意一位都是一个整数
	 * @param dangqian	当前要设置新数字的位数
	 * @param dagqianzhi	当前要设置位数上的值
	 */
	public static void asa(int jingzhi,List<Integer> jisuan,int dangqian,int dagqianzhi) {
//		jingzhi = jingzhi-1;
		if (jingzhi<2) {
			throw new RuntimeException("进制不能小于2");
		}
		
		//如果当设置值大于进制
		if (jingzhi<=dagqianzhi) {
			
			if (dangqian+1<jisuan.size()) {
				
				int redanqian =  dagqianzhi%jingzhi;
				jisuan.set(dangqian, redanqian);
				
				int rexiayiwei = dagqianzhi/jingzhi;
				dangqian = dangqian+1;
				
				dagqianzhi = jisuan.get(dangqian)+rexiayiwei;
				asa(jingzhi, jisuan, dangqian, dagqianzhi);
				
			}else {
				for (int i = 0; i < jisuan.size(); i++) {
					jisuan.set(i, -1);
				}
//				throw new RuntimeException("超过了当前的位数");
				
				
			}

		}else {
			jisuan.set(dangqian, dagqianzhi);
		}
		
		
		
	
		
		
		
	}
	
	
	/**
	 * 
	 * @param a
	 * @param n
	 * @return	返回的是最终的函数方程组，类似于
	 * 			x1 = (P11)*c1*Math.exp(λ1*t) + (P12)*c2*Math.exp(λ2*t)
	 * 			x2 = (P21)*c1*Math.exp(λ1*t) + (P22)*c2*Math.exp(λ2*t)
	 * 
	 * 
	 * 			
	 */
	public static List<List<HanShu>> onepiece(double[][] a,int n) {
		double[] tezhengzhi = tezhengzhi(a);
		for (int i = 0; i < tezhengzhi.length; i++) {
			System.out.println(tezhengzhi[i]);
		}
		
		
		double[][] tezhengxiangliang = tezhengxiangliang(a);
		
		for (int i = 0; i < tezhengzhi.length; i++) {
			for (int j = 0; j < tezhengxiangliang.length; j++) {
				System.out.print(tezhengxiangliang[i][j]+" ");
			}
			System.out.println();
		}
		
		
		HanShu[] yi = tongjieYiBytezhengzhi(tezhengzhi);
		
		System.out.println(yi.length);
		
		List<List<HanShu>> xi = tongjieXiByYi(yi, tezhengxiangliang);
		
		
		List<List<Double>> Ci = new ArrayList<List<Double>>();
		for (int i = 1; i <= n; i++) {
			List<Double> asa = new ArrayList<Double>();
			asa.add(i*1.0);
			asa.add(i*1.0);

			List<Double> asb = new ArrayList<Double>();
			asb.add(-i*1.0);
			asb.add(-i*1.0);
			Ci.add(asa);
			Ci.add(asb);
		}
		System.out.println("--------------------------------");
		for (int i = 0; i < Ci.size(); i++) {
			for (int j = 0; j < Ci.get(i).size(); j++) {
				System.out.print(Ci.get(i).get(j)+"   ");
			}
			System.out.println();
		}
		
		System.out.println("--------------------------------");

		
		
		List<List<HanShu>> result = new ArrayList<List<HanShu>>();
		for (int i = 0; i < Ci.size(); i++) {
			List<Double> list = Ci.get(i);
			
			double[] ci = new double[list.size()];
			for (int j = 0; j < ci.length; j++) {
				ci[j] = list.get(j);
			}
			
			
			List<HanShu> tongjieXiByXiCi = tongjieXiByXiCi(xi, ci);
			result.add(tongjieXiByXiCi);
		}
		
		
		return result;
		
		
//		System.out.println(xi.size()+" tongjieXiByYi ");
//		System.out.println(xi.get(0).size());
//		
//		
//		
//		
//		List<List<HanShu>> tongjieXiCiList = tongjieXiCiList(xi, 2);
//		
//		System.out.println(tongjieXiCiList.size());
//		System.out.println(tongjieXiCiList.get(0).size());
//		return tongjieXiCiList;
		
	}
	
	
	
	
	
	
	
	
	public static void main(String[] args) {
		
//		double[][] a = {
//				{1, 1},
//				{4, -2},
//			};
//		
//		List<List<HanShu>> onepiece = onepiece(a,2);
//		System.out.println(onepiece.size());
//		System.out.println(onepiece.get(0).size());

		double[][] a = {
				{0, 1},
				{-1, 0},
			};
		
		double[] tezhengzhi = tezhengzhi(a);
		for (int i = 0; i < tezhengzhi.length; i++) {
			System.out.println(tezhengzhi[i]);
		}
		
//		
//		System.out.println("===========组合的一个测试================");
//		
//		List<Double> cis = new ArrayList<Double>();
//		cis.add(0.0);
//		int size = 2;
//		for (int i = 1; i < 2; i++) {
//			cis.add(i+0.0);
//			cis.add(-1*(i+0.0));
//		}
//		
//		for (int i = 0; i < cis.size(); i++) {
//			System.out.println(cis.get(i));
//		}
//		System.out.println("-------------");
//		
//		List<List<Double>> zuhe = zuhe(cis, cis.size()-1);
//		for (int i = 0; i < zuhe.size(); i++) {
//			List<Double> list = zuhe.get(i);
//			for (int j = 0; j < list.size(); j++) {
//				System.out.print(list.get(j) + "   ");
//			}
//			System.out.println();
//		}
//		
//		System.out.println("++++++++++++++++++++++++++++++++++++++====");
//		
//		List<Integer> jisuan = new ArrayList<Integer>();
//		jisuan.add(0);
//		jisuan.add(0);
//		int jingzhi = 3;
//		System.out.println(jisuan);
//
//		for (int i = 0; i < 9; i++) {
//			Integer dagqianzhi = jisuan.get(0)+2;
//			asa(jingzhi, jisuan, 0, dagqianzhi);
//			
//			System.out.println(jisuan);
//		}
		
		
		
		
	}



	
	
	
	
	
	
	
	
	
	
	
}
